use std::collections::HashMap;
use std::ffi::OsStr;
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use std::time::Duration;

use fatfs::{FileSystem, Dir, File, Metadata, Date, Time, EntryType};
use fuse3::{FileAttr, FileType, Filesystem, Request, ReplyAttr, ReplyCreate, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyOpen, ReplyStatfs, ReplyWrite};
use log::{debug, info, warn, error};

use crate::error::FatFsError;

/// FAT文件系统FUSE适配器
/// 
/// 这个结构体将FAT文件系统操作适配到FUSE接口，允许在Linux系统上挂载FAT文件系统镜像。
#[derive(Debug)]
pub struct FatFsFuse {
    fs: Arc<FileSystem<File>>,
    root_dir: Arc<Mutex<Dir<File>>>,
    read_only: bool,
    // File handle management
    next_file_handle: u64,
    open_files: Mutex<HashMap<u64, Arc<Mutex<File>>>>,
    open_dirs: Mutex<HashMap<u64, Arc<Mutex<Dir<File>>>>>,
}

impl FatFsFuse {
    pub fn new(fs: Arc<FileSystem<File>>) -> Self {
        let root_dir = fs.root_dir();
        Self {
            fs,
            root_dir: Arc::new(Mutex::new(root_dir)),
            read_only: false,
            next_file_handle: 1,
            open_files: Mutex::new(HashMap::new()),
            open_dirs: Mutex::new(HashMap::new()),
        }
    }

    /// 从文件创建FatFsFuse实例
    /// 
    /// # 参数
    /// - `device`: 包含FAT文件系统的文件
    /// - `read_only`: 是否以只读模式挂载
    /// 
    /// # 返回值
    /// - 成功时返回初始化好的FatFsFuse实例
    /// - 失败时返回相应的错误
    pub fn new_from_file(device: File, read_only: bool) -> Result<Self, FatFsError> {
        use fatfs::{FsOptions, FormatVolumeOptions};
        
        let fs = FileSystem::new(device, FsOptions::new()
            .read_only(read_only))
            .map_err(|e| FatFsError::Other(format!("Failed to mount filesystem: {:?}", e)))?;
            
        Ok(Self::new(Arc::new(fs)))
    }
    
    /// 从文件路径创建FatFsFuse实例
    /// 
    /// # 参数
    /// - `path`: 包含FAT文件系统的文件路径
    /// - `read_only`: 是否以只读模式挂载
    /// 
    /// # 返回值
    /// - 成功时返回初始化好的FatFsFuse实例
    /// - 失败时返回相应的错误
    pub fn from_path<P: AsRef<std::path::Path>>(path: P, read_only: bool) -> Result<Self, FatFsError> {
        let file = File::open(path)
            .map_err(|e| FatFsError::Other(format!("Failed to open file: {}", e)))?;
        Self::new_from_file(file, read_only)
    }

    // Convert FAT time to UNIX time
    fn fat_time_to_unix(date: Date, time: Time) -> Duration {
        use time::{Date, Month, PrimitiveDateTime};
        
        let year = date.year() as i32;
        let month = date.month() as u8;
        let day = date.day() as u8;
        let hour = time.hour() as u8;
        let minute = time.minute() as u8;
        let second = time.second() as u8 * 2; // FAT stores seconds in 2-second increments

        // Create a PrimitiveDateTime and convert to Duration
        let dt = Date::from_calendar_date(year, Month::try_from(month).unwrap(), day)
            .unwrap()
            .with_hms(hour, minute, second)
            .unwrap();
        
        dt.assume_utc() - time::OffsetDateTime::UNIX_EPOCH
    }

    // Convert metadata to FileAttr
    fn metadata_to_attr(&self, metadata: &Metadata) -> Result<FileAttr, FatFsError> {
        let file_type = if metadata.is_dir() {
            FileType::Directory
        } else {
            FileType::RegularFile
        };

        let size = metadata.size();
        let blocks = (size + 511) / 512; // Assuming 512-byte blocks

        // Get creation time
        let created = if let (Some(date), Some(time)) = (metadata.creation_date(), metadata.creation_time()) {
            Self::fat_time_to_unix(date, time)
        } else {
            Duration::from_secs(0)
        };

        // Get modification time
        let modified = if let (Some(date), Some(time)) = (metadata.modification_date(), metadata.modification_time()) {
            Self::fat_time_to_unix(date, time)
        } else {
            Duration::from_secs(0)
        };

        // Get access time (use modification time if not available)
        let accessed = if let (Some(date), Some(time)) = (metadata.access_date(), metadata.access_time()) {
            Self::fat_time_to_unix(date, time)
        } else {
            modified
        };

        Ok(FileAttr {
            ino: metadata.index() as u64,
            size,
            blocks,
            atime: accessed.as_secs(),
            mtime: modified.as_secs(),
            ctime: created.as_secs(),
            crtime: created.as_secs(),
            atimensec: (accessed.subsec_nanos()) as u32,
            mtimensec: (modified.subsec_nanos()) as u32,
            ctimensec: (created.subsec_nanos()) as u32,
            crtimensec: (created.subsec_nanos()) as u32,
            kind: file_type,
            perm: 0o644,
            nlink: 1,
            uid: 0,
            gid: 0,
            rdev: 0,
            blksize: 512,
            padding: 0,
            flags: 0,
        })
    }

    // Find a file or directory by path
    fn find_path(&self, path: &Path) -> Result<(Arc<Mutex<Dir<File>>>, String), FatFsError> {
        debug!("Finding path: {}", path.display());
        
        if path == Path::new("/") {
            debug!("Root path requested");
            return Ok((self.root_dir.clone(), "."));
        }

        let components: Vec<_> = path.components().collect();
        if components.is_empty() || components[0] != std::path::Component::RootDir {
            warn!("Invalid path format: {}", path.display());
            return Err(FatFsError::invalid_path(path.to_string_lossy().to_string()));
        }

        // Special case: single component (e.g., "/file.txt")
        if components.len() == 2 {
            let name = components[1].as_os_str().to_string_lossy().to_string();
            debug!("Single component path: /{}", name);
            return Ok((self.root_dir.clone(), name));
        }

        // Navigate through directories
        let mut current_dir_arc = self.root_dir.clone();
        let mut current_path = String::from("/");
        
        for (i, comp) in components.iter().enumerate().skip(1) {
            let comp_name = comp.as_os_str().to_string_lossy();
            current_path.push_str(&comp_name);
            
            if i < components.len() - 1 { // Not the last component
                debug!("Looking up directory component: {} at path: {}", comp_name, current_path);
                
                let current_dir = current_dir_arc.lock()
                    .map_err(|_| {
                        error!("Failed to lock directory: {}", current_path);
                        FatFsError::other("Failed to lock directory".to_string())
                    })?;
                
                let next_dir = current_dir.open_dir(comp_name.as_ref())
                    .map_err(|_| {
                        warn!("Directory not found: {}", current_path);
                        FatFsError::directory_not_found(current_path.clone())
                    })?;
                
                // Drop the lock before creating a new arc
                drop(current_dir);
                current_dir_arc = Arc::new(Mutex::new(next_dir));
                current_path.push('/');
            }
        }

        // Get the last component name
        let last_comp = components.last()
            .ok_or_else(|| {
                error!("Failed to get last component of path: {}", path.display());
                FatFsError::invalid_path(path.to_string_lossy().to_string())
            })?;
        let name = last_comp.as_os_str().to_string_lossy().to_string();
        
        debug!("Path resolution completed, found: {} in directory", name);

        Ok((current_dir_arc, name))
    }
    
    // Generate a new file handle
    fn new_file_handle(&mut self) -> u64 {
        let handle = self.next_file_handle;
        self.next_file_handle += 1;
        handle
    }
    
    // Get file by handle
    fn get_file_by_handle(&self, fh: u64) -> Result<Arc<Mutex<File>>, FatFsError> {
        let open_files = self.open_files.lock()
            .map_err(|_| FatFsError::Other("Failed to lock open files".to_string()))?;
        
        open_files.get(&fh)
            .ok_or_else(|| FatFsError::Other("Invalid file handle".to_string()))?
            .clone()
    }
    
    // Get directory by handle
    fn get_dir_by_handle(&self, fh: u64) -> Result<Arc<Mutex<Dir<File>>>, FatFsError> {
        let open_dirs = self.open_dirs.lock()
            .map_err(|_| FatFsError::Other("Failed to lock open dirs".to_string()))?;
        
        open_dirs.get(&fh)
            .ok_or_else(|| FatFsError::Other("Invalid directory handle".to_string()))?
            .clone()
    }
}

impl Filesystem for FatFsFuse {
    type Error = FatFsError;

    fn init(&mut self, _req: &Request<'_>, conn: &FuseConnInfo<'_>) -> Result<(), Self::Error> {
        log::info!("FUSE filesystem initialized");
        // Set read-only mode based on connection info
        self.read_only = conn.flags & fuse3::FUSE_READONLY != 0;
        Ok(())
    }

    fn destroy(&mut self, _req: Option<&Request<'_>>) {
        log::info!("FUSE filesystem destroyed");
        // Clean up open files and directories
        self.open_files.lock().unwrap().clear();
        self.open_dirs.lock().unwrap().clear();
    }

    fn lookup(&mut self, _req: &Request<'_>, _parent: u64, name: &OsStr, reply: ReplyEntry) -> Result<(), Self::Error> {
        debug!("lookup: name={}", name.to_string_lossy());
        
        // For simplicity, we're only handling files in the root directory for now
        let root_dir = self.root_dir.lock()
            .map_err(|_| {
                error!("Failed to lock root directory");
                FatFsError::Other("Failed to lock root directory".to_string())
            })?;
        
        // Try to get metadata for the requested entry
        match root_dir.metadata(name) {
            Ok(metadata) => {
                let attr = self.metadata_to_attr(&metadata)?;
                debug!("Found entry: {}, is_dir={}", name.to_string_lossy(), metadata.is_dir());
                reply.entry(&Duration::new(1, 0), &attr, 0);
                Ok(())
            },
            Err(_) => {
                let name_str = name.to_string_lossy().to_string();
                warn!("Entry '{}' not found in directory", name_str);
                Err(FatFsError::FileNotFound(name_str))
            }
        }
    }

    fn getattr(&mut self, _req: &Request<'_>, ino: u64, reply: ReplyAttr) -> Result<(), Self::Error> {
        debug!("getattr: ino={}", ino);
        
        if ino == 1 { // Root directory
            let root_dir = self.root_dir.lock()
                .map_err(|_| {
                    error!("Failed to lock root directory");
                    FatFsError::Other("Failed to lock root directory".to_string())
                })?;
            
            match root_dir.metadata(".") {
                Ok(metadata) => {
                    let attr = self.metadata_to_attr(&metadata)?;
                    debug!("Returning root directory attributes");
                    reply.attr(&Duration::new(1, 0), &attr);
                    Ok(())
                },
                Err(e) => {
                    error!("Failed to get root directory metadata: {:?}", e);
                    Err(FatFsError::Other(format!("Failed to get root directory metadata: {:?}", e)))
                }
            }
        } else {
            // In a complete implementation, we'd map inode numbers to files
            warn!("Request for unknown inode: {}", ino);
            Err(FatFsError::FileNotFound(format!("inode {}", ino)))
        }
    }

    fn readdir(&mut self, _req: &Request<'_>, _ino: u64, _fh: u64, offset: i64, mut reply: ReplyDirectory) -> Result<(), Self::Error> {
        let root_dir = self.root_dir.lock()
            .map_err(|_| FatFsError::Other("Failed to lock root directory".to_string()))?;
        
        let mut index = 0;
        
        // Handle . and .. entries
        if offset == 0 {
            reply.add(1, 0, FileType::Directory, ".");
            reply.add(1, 1, FileType::Directory, "..");
            index = 2;
        }
        
        // Iterate through directory entries
        for (entry_name, entry_metadata) in root_dir.iter() {
            if index as i64 > offset {
                let attr = self.metadata_to_attr(&entry_metadata)?;
                let file_type = match entry_metadata.is_dir() {
                    true => FileType::Directory,
                    false => FileType::RegularFile,
                };
                reply.add(attr.ino, index as i64, file_type, &entry_name);
            }
            index += 1;
        }
        
        reply.ok();
        Ok(())
    }

    fn opendir(&mut self, _req: &Request<'_>, ino: u64, _flags: u32, reply: ReplyOpen) -> Result<(), Self::Error> {
        if ino != 1 { // Only root directory for now
            return Err(FatFsError::NotADirectory(format!("inode {}", ino)));
        }
        
        let handle = self.new_file_handle();
        let dir_arc = self.root_dir.clone();
        
        self.open_dirs.lock()
            .map_err(|_| FatFsError::Other("Failed to lock open dirs".to_string()))?
            .insert(handle, dir_arc);
        
        reply.open(handle, 0);
        Ok(())
    }

    fn releasedir(&mut self, _req: &Request<'_>, _ino: u64, fh: u64, _flags: u32, _lock_owner: u64, _flush: bool) -> Result<(), Self::Error> {
        self.open_dirs.lock()
            .map_err(|_| FatFsError::Other("Failed to lock open dirs".to_string()))?
            .remove(&fh);
        Ok(())
    }

    fn open(&mut self, _req: &Request<'_>, _ino: u64, flags: u32, reply: ReplyOpen) -> Result<(), Self::Error> {
        // In a real implementation, we'd open the actual file based on inode
        // For now, we're just tracking file handles
        
        // Check if read-only and opening for writing
        if self.read_only && (flags & 0o3) != 0 {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // Generate a new file handle
        let handle = self.new_file_handle();
        reply.open(handle, 0);
        Ok(())
    }

    fn read(&mut self, _req: &Request<'_>, ino: u64, fh: u64, offset: i64, size: u32, reply: ReplyData) -> Result<(), Self::Error> {
        // In a real implementation, we'd read from the actual file
        // For now, just return empty data
        let mut buffer = vec![0; size as usize];
        reply.data(&buffer[..0]);
        Ok(())
    }

    fn write(&mut self, _req: &Request<'_>, ino: u64, fh: u64, offset: i64, data: &[u8], _flags: u32, reply: ReplyWrite) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // In a real implementation, we'd write to the actual file
        reply.write(data.len() as u32);
        Ok(())
    }

    fn release(&mut self, _req: &Request<'_>, _ino: u64, fh: u64, _flags: u32, _lock_owner: u64, _flush: bool) -> Result<(), Self::Error> {
        // Remove the file handle from open files
        self.open_files.lock()
            .map_err(|_| FatFsError::Other("Failed to lock open files".to_string()))?
            .remove(&fh);
        Ok(())
    }

    fn mkdir(&mut self, _req: &Request<'_>, _parent: u64, name: &OsStr, _mode: u32, reply: ReplyEntry) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        let mut root_dir = self.root_dir.lock()
            .map_err(|_| FatFsError::Other("Failed to lock root directory".to_string()))?;
        
        // Try to create the directory
        root_dir.create_dir(name)
            .map_err(|_| FatFsError::DirectoryExists(name.to_string_lossy().to_string()))?;
        
        // Get metadata of the new directory
        let metadata = root_dir.metadata(name)?;
        let attr = self.metadata_to_attr(&metadata)?;
        reply.entry(&Duration::new(1, 0), &attr, 0);
        Ok(())
    }

    fn create(&mut self, _req: &Request<'_>, _parent: u64, name: &OsStr, _mode: u32, flags: u32, reply: ReplyCreate) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        let mut root_dir = self.root_dir.lock()
            .map_err(|_| FatFsError::Other("Failed to lock root directory".to_string()))?;
        
        // Try to create the file
        let file = root_dir.create_file(name)
            .map_err(|_| FatFsError::FileExists(name.to_string_lossy().to_string()))?;
        
        // Store the open file
        let handle = self.new_file_handle();
        let file_arc = Arc::new(Mutex::new(file));
        
        self.open_files.lock()
            .map_err(|_| FatFsError::Other("Failed to lock open files".to_string()))?
            .insert(handle, file_arc);
        
        // Get metadata of the new file
        let metadata = root_dir.metadata(name)?;
        let attr = self.metadata_to_attr(&metadata)?;
        reply.created(&Duration::new(1, 0), &attr, handle, flags);
        Ok(())
    }

    fn unlink(&mut self, _req: &Request<'_>, _parent: u64, name: &OsStr, reply: ReplyEmpty) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        let mut root_dir = self.root_dir.lock()
            .map_err(|_| FatFsError::Other("Failed to lock root directory".to_string()))?;
        
        // Try to remove the file
        root_dir.remove_file(name)
            .map_err(|_| FatFsError::FileNotFound(name.to_string_lossy().to_string()))?;
        
        reply.ok();
        Ok(())
    }

    fn rmdir(&mut self, _req: &Request<'_>, _parent: u64, name: &OsStr, reply: ReplyEmpty) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        let mut root_dir = self.root_dir.lock()
            .map_err(|_| FatFsError::Other("Failed to lock root directory".to_string()))?;
        
        // Try to remove the directory
        root_dir.remove_dir(name)
            .map_err(|_| FatFsError::DirectoryNotFound(name.to_string_lossy().to_string()))?;
        
        reply.ok();
        Ok(())
    }

    fn rename(&mut self, _req: &Request<'_>, _parent: u64, name: &OsStr, _newparent: u64, newname: &OsStr, reply: ReplyEmpty) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        let mut root_dir = self.root_dir.lock()
            .map_err(|_| FatFsError::Other("Failed to lock root directory".to_string()))?;
        
        // Try to rename the entry
        root_dir.rename(name, newname)
            .map_err(|_| FatFsError::Other("Failed to rename".to_string()))?;
        
        reply.ok();
        Ok(())
    }

    fn statfs(&mut self, _req: &Request<'_>, _ino: u64, reply: ReplyStatfs) -> Result<(), Self::Error> {
        // Get filesystem information
        let fs_info = self.fs.info();
        let total_sectors = fs_info.total_sectors() as u64;
        let free_sectors = fs_info.free_sectors() as u64;
        let bytes_per_sector = fs_info.bytes_per_sector() as u32;
        let block_size = 4096; // Standard block size
        let blocks = (total_sectors * bytes_per_sector as u64 + block_size - 1) / block_size;
        let free_blocks = (free_sectors * bytes_per_sector as u64 + block_size - 1) / block_size;
        
        reply.statfs(
            blocks,        // blocks
            free_blocks,   // bfree
            free_blocks,   // bavail
            fs_info.cluster_count() as u64, // files
            fs_info.free_clusters() as u64, // ffree
            block_size as u32,  // bsize
            4096,         // namelen
            0,            // frsize (fragment size)
        );
        Ok(())
    }
    
    fn truncate(&mut self, _req: &Request<'_>, _ino: u64, size: u64, reply: ReplyEmpty) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // In a real implementation, we'd truncate the actual file
        reply.ok();
        Ok(())
    }
    
    fn ftruncate(&mut self, _req: &Request<'_>, _ino: u64, fh: u64, size: u64, reply: ReplyEmpty) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // In a real implementation, we'd truncate the opened file
        reply.ok();
        Ok(())
    }
    
    fn flush(&mut self, _req: &Request<'_>, _ino: u64, fh: u64, _lock_owner: u64, _flush: bool, reply: ReplyEmpty) -> Result<(), Self::Error> {
        // In a real implementation, we'd flush the file buffers
        reply.ok();
        Ok(())
    }
    
    fn fsync(&mut self, _req: &Request<'_>, _ino: u64, fh: u64, _datasync: bool, reply: ReplyEmpty) -> Result<(), Self::Error> {
        // In a real implementation, we'd sync the file to disk
        reply.ok();
        Ok(())
    }
    
    fn fsyncdir(&mut self, _req: &Request<'_>, _ino: u64, fh: u64, _datasync: bool, reply: ReplyEmpty) -> Result<(), Self::Error> {
        // In a real implementation, we'd sync the directory to disk
        reply.ok();
        Ok(())
    }
    
    fn access(&mut self, _req: &Request<'_>, _ino: u64, _mask: u32, reply: ReplyEmpty) -> Result<(), Self::Error> {
        // In a real implementation, we'd check access permissions
        // For now, we'll allow all access
        reply.ok();
        Ok(())
    }
    
    fn create(&mut self, req: &Request<'_>, parent: u64, name: &str, mode: u32, reply: ReplyCreate) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // In a real implementation, we'd create the file
        let fh = self.new_file_handle();
        
        let attr = FileAttr {
            ino: 0, // In a real implementation, we'd get the actual inode
            size: 0,
            blocks: 0,
            atime: SystemTime::now(),
            mtime: SystemTime::now(),
            ctime: SystemTime::now(),
            crtime: SystemTime::now(),
            kind: FileType::RegularFile,
            perm: 0o644,
            nlink: 1,
            uid: req.uid(),
            gid: req.gid(),
            rdev: 0,
            flags: 0,
            blksize: 512,
        };
        
        reply.created(&attr, fh);
        Ok(())
    }
    
    fn write(&mut self, _req: &Request<'_>, _ino: u64, fh: u64, _offset: i64, _data: &[u8], reply: ReplyWrite) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // In a real implementation, we'd write to the file
        reply.written(_data.len());
        Ok(())
    }
    
    fn mkdir(&mut self, _req: &Request<'_>, parent: u64, name: &str, mode: u32, reply: ReplyEntry) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // In a real implementation, we'd create the directory
        let attr = FileAttr {
            ino: 0, // In a real implementation, we'd get the actual inode
            size: 0,
            blocks: 0,
            atime: SystemTime::now(),
            mtime: SystemTime::now(),
            ctime: SystemTime::now(),
            crtime: SystemTime::now(),
            kind: FileType::Directory,
            perm: 0o755,
            nlink: 2, // Directory entries count themselves and . and ..
            uid: 0,
            gid: 0,
            rdev: 0,
            flags: 0,
            blksize: 512,
        };
        
        reply.entry(&Timeout::default(), &attr, 0);
        Ok(())
    }
    
    fn rmdir(&mut self, _req: &Request<'_>, parent: u64, name: &str, reply: ReplyEmpty) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // In a real implementation, we'd remove the directory
        reply.ok();
        Ok(())
    }
    
    fn unlink(&mut self, _req: &Request<'_>, parent: u64, name: &str, reply: ReplyEmpty) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // In a real implementation, we'd remove the file
        reply.ok();
        Ok(())
    }
    
    fn rename(&mut self, _req: &Request<'_>, parent: u64, name: &str, newparent: u64, newname: &str, reply: ReplyEmpty) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // In a real implementation, we'd rename the file or directory
        reply.ok();
        Ok(())
    }
    
    fn chmod(&mut self, _req: &Request<'_>, _ino: u64, _mode: u32, reply: ReplyEmpty) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // In a real implementation, we'd change the mode
        reply.ok();
        Ok(())
    }
    
    fn chown(&mut self, _req: &Request<'_>, _ino: u64, _uid: Option<u32>, _gid: Option<u32>, reply: ReplyEmpty) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // In a real implementation, we'd change the ownership
        reply.ok();
        Ok(())
    }
    
    fn utimens(&mut self, _req: &Request<'_>, _ino: u64, _atime: &TimeSpec, _mtime: &TimeSpec, reply: ReplyEmpty) -> Result<(), Self::Error> {
        if self.read_only {
            return Err(FatFsError::ReadOnlyFilesystem);
        }
        
        // In a real implementation, we'd update the times
        reply.ok();
        Ok(())
    }
}